#pragma once

#include "types.h"
#include <random>

OPEN_JLIB_NS


struct Random {
  
  inline Random () noexcept : _engine(__engine()) {
  }

  inline explicit Random (u32 seed) noexcept : _engine(seed) {
  }

  
  inline void seed () noexcept {
    _engine.seed(__engine());
  }

  inline void seed (u32 seed) noexcept {
    _engine.seed(seed);
  }
  

  inline bool bernoulli (f64 p = 0.5) {
    return std::bernoulli_distribution(p)(_engine);
  }

  template<typename _Type>
  inline _Type uniformi (_Type min, _Type max) noexcept {
    return std::uniform_int_distribution<_Type>(min, max)(_engine);
  }

  template<typename _Type>
  inline _Type uniformf (_Type min, _Type max) noexcept {
    return std::uniform_real_distribution<_Type>(min, max)(_engine);
  }

  template <typename _Type>
  inline _Type normal (_Type mean, _Type stddev) {
    return std::normal_distribution<_Type>(mean, stddev)(_engine);
  }

public:
  std::mt19937 _engine;
  static std::random_device __device;
  static std::mt19937 __engine;
};


CLOSE_JLIB_NS